class Snake extends egret.Sprite{

	static LEFT:number = 0;
	static UP:number = 1;
	static RIGHT:number = 2;
	static DOWN:number = 3;

	static p:Point;

	static isAgainst(d1:number,d2:number):boolean{
		if(Math.abs(d1 - d2) == 2){
			return true;
		}
		return false;
	}

	static getMoveVec(dir:number):Point{
		if(Snake.p == null){
			Snake.p = new Point(); 
		}
		switch(dir){
			case Snake.LEFT:
				Snake.p.setTo(-1,0);
			break;
			case Snake.UP:
				Snake.p.setTo(0,-1);
			break;
			case Snake.RIGHT:
				Snake.p.setTo(1,0);
			break;
			case Snake.DOWN:
				Snake.p.setTo(0,1);
			break;
		}
		return Snake.p;
	}

	curDir:number;
	data:Array<Point>;
	len:number;
	gx:number;
	gy:number;
	private turningList:Array<Point>;
	private unitList:Array<Unit>;

	constructor(len:number,dir:number,x:number = 0,y:number = 0){
		super();
		this.turningList = [];
		this.data = [];
		this.unitList = [];
		this.reset(len,dir,x,y);
	}

	reset(len:number,dir:number,x:number = 0,y:number = 0){
		this.turningList.length = 0;
		this.data.length = 0;
		for(let u of this.unitList){
			u.destroy();
		}
		this.unitList.length = 0;
		this.gx = x;
		this.gy = y;
		this.curDir = dir;
		this.len = 0;
		for(let i = 0;i < len; i++){
			this.add(false);
		}
		this.draw();
	}

	add(drawNow:boolean = true){
		let p:Point = Snake.getMoveVec(this.curDir);
		this.data.push(new Point(this.curDir,this.gx,this.gy));
		this.gx += p.x;
		this.gy += p.y;
		this.len ++;
		if(drawNow){
			this.draw();
		}
	}

	move(dir:number,drawNow:boolean = true){
		if(Snake.isAgainst(dir,this.curDir)){
			return;
		}
		if(this.curDir != dir){
			this.turningList.push(new Point(dir,this.gx,this.gy));
			this.curDir = dir;
		}
		for(let p of this.data){
			for(let tp of this.turningList){
				if(tp.x == p.x && tp.y == p.y){
					p.dir = tp.dir;
				}
			}
			let op:Point = Snake.getMoveVec(p.dir);
			p.x += op.x;
			p.y += op.y;
		}
		let op:Point = Snake.getMoveVec(this.curDir);
		this.gx += op.x;
		this.gy += op.y;
		if(drawNow){
			this.draw();
		}

		for(let i:number = this.turningList.length - 1;i>=0;i--){
			let tp:Point = this.turningList[i];
			let flag:boolean = true;
			for(let p of this.data){
				if(p.x == tp.x && p.y == tp.y){
					flag = false;
					break;
				}
			}
			if(flag){
				this.turningList.splice(i,1);
			}
		}
	}

	hitSelf():boolean{
		for(let p of this.data){
			if(p.x == this.gx && this.gy == p.y){
				return true;
			}
		}
		return false;
	}

	private draw(){
		for(let u of this.unitList){
			u.destroy();
		}
		this.unitList.length = 0;
		for(let p of this.data){
			let u:Unit = Unit.create(0);
			u.reset(p.x,p.y);
			this.addChild(u);
			this.unitList.push(u);
		}
	}
}
